package socket;

import java.io.*;
import java.net.Socket;
import java.util.Scanner;

/**
*   聊天室客户端
 */
public class Client4_29 {
    /*
    java.net.Socket 套接字
    Socket封装了TCP协议的通讯细节，我们通过它可以与远端计算机
    建立连接，并通过它获取两个流（一个输入，一个输出），然后对两
    个流的数据读写完成与远端计算机的数据交互工作。
    我们可以把Socket想象成一个电话，电话有一个听筒（输入流），
    一个麦克风（输出流），通过它们就可以与对方交流了。
     */
    private Socket socket;
    /*
    构造方法，用来初始化客户端的
     */
    public Client4_29(){
        try {
            System.out.println("正在连接服务端....");
            /*
            实例化Socket时要传入两个参数
            参数1：服务器的地址信息
                可以是IP地址，如果连接本机可以写“localhost”
             参数2：服务器开启的服务端口
             我们通过IP找到网络上的服务端计算机，通过端口连接运行在该
             机器上的服务端应用程序
             实例化的过程就是链接的过程，如果连接失败会抛出异常：
             java.net.ConnectException:Connection refused:connect
             */
            socket=new Socket("localhost",8088);
            System.out.println("与服务端建立连接...");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /*
    客户端开始的方法
     */
    public void start(){
        try {
            //启动读取服务端发送过来消息的线程。
            ServerHandler handler=new ServerHandler();
            Thread t=new Thread(handler);
            t.setDaemon(true);
            t.start();
            /*
            Socket提供了一个方法：
            OutputStream getOutputStream()
            该方法获取的字节输出流写出的字节会通过网络发送给对方计算机。
             */
            OutputStream out=socket.getOutputStream();
            //低级流，将字节通过网路发送给对方
            OutputStreamWriter ost=new OutputStreamWriter(out,"utf-8");
            //高级流，负责衔接字节流与字符流，并将写出的字符按指定字符集转字节
            BufferedWriter bw=new BufferedWriter(ost);
            //高级流，负责块读写文本数据加速
            PrintWriter pw=new PrintWriter(bw,true);
            //高级流，负责按行写出字符串，自动行刷新
            Scanner scan=new Scanner(System.in);
            System.out.println("小伙子开始你的发言：");
            while(true){

                String a=scan.nextLine();
                if(a.equals("exit")){
                    break;
                }
                pw.println(a);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                /*
                通讯完毕后调用socket的close方法。
                该方法会给对方发送断开信号。
                 */
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        Client4_29 client=new Client4_29();
        client.start();
    }
    /*
    该线程负责接受服务端发送过来的信息。
     */
    private class ServerHandler implements Runnable{
        @Override
        public void run() {
            //通过socket获取输入流读取服务端发送过来的信息
            try {
                InputStream in=socket.getInputStream();
                InputStreamReader isr=new InputStreamReader(in,"utf-8");
                BufferedReader br=new BufferedReader(isr);
                String line;
                //循环读取服务端发送过来的每一行字符串。
                while((line=br.readLine())!=null){
                    System.out.println(line);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }
}
